home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 13
/
CU Amiga Magazine's Super CD-ROM 13 (1997)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1997-08].iso
/
CUCD
/
Graphics
/
irit70
/
src
/
irit
/
freefrm2.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-13
|
76KB
|
1,823 lines
/*****************************************************************************
* "Irit" - the 3d (not only polygonal) solid modeller. *
* *
* Written by: Gershon Elber Ver 0.2, Mar. 1990 *
******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology *
******************************************************************************
* Module to provide the required interfact for the cagd library for the *
* free form surfaces and curves. *
*****************************************************************************/
#include <stdio.h>
#include <math.h>
#include "program.h"
#include "allocate.h"
#include "attribut.h"
#include "objects.h"
#include "primitiv.h"
#include "geomat3d.h"
#include "ip_cnvrt.h"
#include "bool_lib.h"
#include "freeform.h"
static IPObjectStruct *ComputeCurveIsoLines(IPObjectStruct *PObj,
int Optimal);
static IPObjectStruct *ComputeSurfaceIsoLines(IPObjectStruct *PObj,
int Optimal);
static IPObjectStruct *ComputeTrimSrfIsoLines(IPObjectStruct *PObj,
int Optimal);
static IPObjectStruct *ComputeTrivarIsoLines(IPObjectStruct *PObj,
int Optimal);
static IPObjectStruct *ComputeTriSrfIsoLines(IPObjectStruct *PObj,
int Optimal);
/*****************************************************************************
* DESCRIPTION: M
* Routine to reverse a curve. M
* *
* PARAMETERS: M
* CrvObj: Curve to reverse its parametrization. M
* *
* RETURN VALUE: M
* IPObjectStruct *: Reversed curve. M
* *
* KEYWORDS: M
* CurveReverse M
*****************************************************************************/
IPObjectStruct *CurveReverse(IPObjectStruct *CrvObj)
{
CagdCrvStruct
*RevCrv = CagdCrvReverse(CrvObj -> U.Crvs);
if (RevCrv == NULL)
return NULL;
CrvObj = GenCRVObject(RevCrv);
return CrvObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to reverse a surface. M
* *
* PARAMETERS: M
* SrfObj: Surface to reverse. M
* *
* RETURN VALUE: M
* IPObjectStruct *: Reversed surface. The normal of the reversed M
* surface is flipped with respected to the original M
* surface, SrfObj, by 180 degrees. M
* *
* KEYWORDS: M
* SurfaceReverse M
*****************************************************************************/
IPObjectStruct *SurfaceReverse(IPObjectStruct *SrfObj)
{
CagdSrfStruct
*RevSrf = CagdSrfReverse(SrfObj -> U.Srfs);
if (RevSrf == NULL)
return NULL;
SrfObj = GenSRFObject(RevSrf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: *
* Routine to convert curve(s) to a piecewise linear polyline approximation *
* and convert its control polygon into polyline as well. *
* *
* PARAMETERS: *
* PObj: Curves to approximate using piecewise linear approximation. *
* Optimal: Do we want an optimal sampling but expensive approach? *
* *
* RETURN VALUE: *
* IPObjectStruct *: A polyline approximation to PObj. *
*****************************************************************************/
static IPObjectStruct *ComputeCurveIsoLines(IPObjectStruct *PObj, int Optimal)
{
int Resolution = GetResolution(FALSE);
IPObjectStruct *PObjPoly;
CagdCrvStruct *Crv;
if (!IP_IS_CRV_OBJ(PObj))
IritFatalError("Curve was expected.");
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
PObjPoly = GenPOLYObject(NULL);
PObjPoly -> Attrs = AttrCopyAttributes(PObj -> Attrs);
IP_SET_POLYLINE_OBJ(PObjPoly);
for (Crv = PObj -> U.Crvs; Crv != NULL; Crv = Crv -> Pnext) {
IPPolygonStruct *Poly;
Poly = IritCurve2Polylines(Crv, Resolution,
(SymbCrvApproxMethodType) Optimal);
Poly -> Pnext = PObjPoly -> U.Pl;
PObjPoly -> U.Pl = Poly;
}
return PObjPoly;
}
/*****************************************************************************
* DESCRIPTION: *
* Routine to convert a surface to a set of piecewise linear polyline *
* approximation and convert its control mesh into set of polyline as well. *
* *
* PARAMETERS: *
* PObj: Surfaces to apporximate as a mesh of piecewise linear *
* isocurves. *
* Optimal: Do we want an optimal sampling but expensive approach? *
* *
* RETURN VALUE: *
* IPObjectStruct *: A polyline object approximating PObj. *
*****************************************************************************/
static IPObjectStruct *ComputeSurfaceIsoLines(IPObjectStruct *PObj,
int Optimal)
{
int Resolution = GetResolution(FALSE);
IPObjectStruct *PObjPolys;
CagdSrfStruct *Srf;
if (!IP_IS_SRF_OBJ(PObj))
IritFatalError("Surface was expected.");
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
PObjPolys = GenPOLYObject(NULL);
PObjPolys -> Attrs = AttrCopyAttributes(PObj -> Attrs);
IP_SET_POLYLINE_OBJ(PObjPolys);
for (Srf = PObj -> U.Srfs; Srf != NULL; Srf = Srf -> Pnext) {
int NumOfIso[2];
IPPolygonStruct *Polys, *PolyTmp;
NumOfIso[0] = NumOfIso[1] = -Resolution;
Polys = IritSurface2Polylines(Srf, NumOfIso, Resolution,
(SymbCrvApproxMethodType) Optimal);
for (PolyTmp = Polys;
PolyTmp -> Pnext != NULL;
PolyTmp = PolyTmp -> Pnext);
PolyTmp -> Pnext = PObjPolys -> U.Pl;
PObjPolys -> U.Pl = Polys;
}
return PObjPolys;
}
/*****************************************************************************
* DESCRIPTION: *
* Routine to convert a trimmed surface to a set of piecewise linear polyline *
* approximation and convert its control mesh into set of polyline as well. *
* *
* PARAMETERS: *
* PObj: Trimmed surfaces to apporximate as a mesh of piecewise *
* linear isocurves. *
* Optimal: Do we want an optimal sampling but expensive approach? *
* *
* RETURN VALUE: *
* IPObjectStruct *: A polyline object approximating PObj. *
*****************************************************************************/
static IPObjectStruct *ComputeTrimSrfIsoLines(IPObjectStruct *PObj,
int Optimal)
{
int Resolution = GetResolution(FALSE);
IPObjectStruct *PObjPolys;
TrimSrfStruct *TrimSrf;
if (!IP_IS_TRIMSRF_OBJ(PObj))
IritFatalError("Trimmed surface was expected.");
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
PObjPolys = GenPOLYObject(NULL);
PObjPolys -> Attrs = AttrCopyAttributes(PObj -> Attrs);
IP_SET_POLYLINE_OBJ(PObjPolys);
for (TrimSrf = PObj -> U.TrimSrfs;
TrimSrf != NULL;
TrimSrf = TrimSrf -> Pnext) {
int NumOfIso[2];
IPPolygonStruct *Polys, *PolyTmp;
NumOfIso[0] = NumOfIso[1] = -Resolution;
Polys = IritTrimSrf2Polylines(TrimSrf, NumOfIso, Resolution,
(SymbCrvApproxMethodType) Optimal,
TRUE, TRUE);
for (PolyTmp = Polys;
PolyTmp -> Pnext != NULL;
PolyTmp = PolyTmp -> Pnext);
PolyTmp -> Pnext = PObjPolys -> U.Pl;
PObjPolys -> U.Pl = Polys;
}
return PObjPolys;
}
/*****************************************************************************
* DESCRIPTION: *
* Routine to convert a trimmed surface to a set of piecewise linear polyline *
* approximation and convert its control mesh into set of polyline as well. *
* *
* PARAMETERS: *
* PObj: Trimmed surfaces to apporximate as a mesh of piecewise *
* linear isocurves. *
* Optimal: Do we want an optimal sampling but expensive approach? *
* *
* RETURN VALUE: *
* IPObjectStruct *: A polyline object approximating PObj. *
*****************************************************************************/
static IPObjectStruct *ComputeTrivarIsoLines(IPObjectStruct *PObj,
int Optimal)
{
int Resolution = GetResolution(FALSE);
IPObjectStruct *PObjPolys;
TrivTVStruct *Trivar;
if (!IP_IS_TRIVAR_OBJ(PObj))
IritFatalError("Trivariate function was expected.");
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
PObjPolys = GenPOLYObject(NULL);
PObjPolys -> Attrs = AttrCopyAttributes(PObj -> Attrs);
IP_SET_POLYLINE_OBJ(PObjPolys);
for (Trivar = PObj -> U.Trivars;
Trivar != NULL;
Trivar = Trivar -> Pnext) {
int NumOfIso[3],
Res = MAX(Resolution / 2, 2);
IPPolygonStruct *Polys, *PolyTmp;
NumOfIso[0] = NumOfIso[1] = NumOfIso[2] = -Res;
Polys = IritTrivar2Polylines(Trivar, NumOfIso, Resolution,
(SymbCrvApproxMethodType) Optimal);
for (PolyTmp = Polys;
PolyTmp -> Pnext != NULL;
PolyTmp = PolyTmp -> Pnext);
PolyTmp -> Pnext = PObjPolys -> U.Pl;
PObjPolys -> U.Pl = Polys;
}
return PObjPolys;
}
/*****************************************************************************
* DESCRIPTION: *
* Routine to convert a triangular surface to a set of piecewise linear *
* polyline approximation and convert its control mesh into set of polyline *
* as well. *
* *
* PARAMETERS: *
* PObj: Triangular surfaces to apporximate as a mesh of piecewise *
* linear isocurves. *
* Optimal: Do we want an optimal sampling but expensive approach? *
* *
* RETURN VALUE: *
* IPObjectStruct *: A polyline object approximating PObj. *
*****************************************************************************/
static IPObjectStruct *ComputeTriSrfIsoLines(IPObjectStruct *PObj,
int Optimal)
{
int Resolution = GetResolution(FALSE);
IPObjectStruct *PObjPolys;
TrngTriangSrfStruct *TriSrf;
if (!IP_IS_TRISRF_OBJ(PObj))
IritFatalError("Triangular surface was expected.");
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
PObjPolys = GenPOLYObject(NULL);
PObjPolys -> Attrs = AttrCopyAttributes(PObj -> Attrs);
IP_SET_POLYLINE_OBJ(PObjPolys);
for (TriSrf = PObj -> U.TriSrfs;
TriSrf != NULL;
TriSrf = TriSrf -> Pnext) {
int NumOfIso[3];
IPPolygonStruct *Polys, *PolyTmp;
NumOfIso[0] = NumOfIso[1] = NumOfIso[2] = -Resolution;
Polys = IritTriSrf2Polylines(TriSrf, NumOfIso, Resolution, Optimal);
for (PolyTmp = Polys;
PolyTmp -> Pnext != NULL;
PolyTmp = PolyTmp -> Pnext);
PolyTmp -> Pnext = PObjPolys -> U.Pl;
PObjPolys -> U.Pl = Polys;
}
return PObjPolys;
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to convert a surface to a set of polygons approximating it. M
* Result is saved as an attribute on the surface. M
* If, however, approximation already exists, no computation is performed. M
* *
* PARAMETERS: M
* PObj: Surface to approximate using polygons. M
* Normals: Compute normals as well, if TRUE. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* ComputeSurfacePolygons M
*****************************************************************************/
void ComputeSurfacePolygons(IPObjectStruct *PObj, int Normals)
{
int Resolution = GetResolution(FALSE),
FourPerFlat = GetFourPerFlat(),
PolyApproxOpt = GetPolyApproxOptimal(),
PolyApproxUV = GetPolyApproxUV(),
BoolUVBooleanState = BoolSetParamSurfaceUVVals(TRUE);
RealType t,
RelResolution = AttrGetObjectRealAttrib(PObj, "resolution"),
Tolerance = GetPolyApproxTol();
IPPolygonStruct *Polys;
IPObjectStruct *PObjPoly;
BoolSetParamSurfaceUVVals(BoolUVBooleanState);/* Restore bool_lib state. */
if (AttrGetObjectObjAttrib(PObj, "_polygons") != NULL)
return;
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
if (RelResolution < IP_ATTR_BAD_REAL)
Resolution = REAL_TO_INT(Resolution * RelResolution);
#ifndef __MSDOS__
/* Make the resolution more reasonable (very slow on MSDOS). */
Resolution *= 2;
#endif /* __MSDOS__ */
if (AttrGetObjectStrAttrib(PObj, "twoperflat") != NULL)
FourPerFlat = FALSE;
if (AttrGetObjectStrAttrib(PObj, "fourperflat") != NULL)
FourPerFlat = TRUE;
if ((t = AttrGetObjectRealAttrib(PObj, "u_resolution")) < IP_ATTR_BAD_REAL)
AttrSetRealAttrib(&PObj -> U.Srfs -> Attr, "u_resolution", t);
if ((t = AttrGetObjectRealAttrib(PObj, "v_resolution")) < IP_ATTR_BAD_REAL)
AttrSetRealAttrib(&PObj -> U.Srfs -> Attr, "v_resolution", t);
Polys = IritSurface2Polygons(PObj -> U.Srfs, FourPerFlat,
PolyApproxOpt ? Tolerance : Resolution,
PolyApproxUV || BoolUVBooleanState,
Normals, PolyApproxOpt);
PObjPoly = GenPolyObject("", Polys, NULL);
PObjPoly -> Attrs = AttrCopyAttributes(PObj -> Attrs);
AttrSetObjectObjAttrib(PObj, "_polygons", PObjPoly, FALSE);
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to convert a triangular surface to a set of polygons M
* approximating it. M
* Result is saved as an attribute on the surface. M
* If, however, approximation already exists, no computation is performed. M
* *
* PARAMETERS: M
* PObj: Triangular surface to approximate using polygons. M
* Normals: Compute normals as well, if TRUE. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* ComputeTriSrfPolygons M
*****************************************************************************/
void ComputeTriSrfPolygons(IPObjectStruct *PObj, int Normals)
{
int Resolution = GetResolution(FALSE),
PolyApproxOpt = GetPolyApproxOptimal(),
PolyApproxUV = GetPolyApproxUV(),
BoolUVBooleanState = BoolSetParamSurfaceUVVals(TRUE);
RealType
RelResolution = AttrGetObjectRealAttrib(PObj, "resolution"),
Tolerance = GetPolyApproxTol();
IPPolygonStruct *Polys;
IPObjectStruct *PObjPoly;
BoolSetParamSurfaceUVVals(BoolUVBooleanState);/* Restore bool_lib state. */
if (AttrGetObjectObjAttrib(PObj, "_polygons") != NULL)
return;
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
if (RelResolution < IP_ATTR_BAD_REAL)
Resolution = REAL_TO_INT(Resolution * RelResolution);
#ifndef __MSDOS__
/* Make the resolution more reasonable (very slow on MSDOS). */
Resolution *= 2;
#endif /* __MSDOS__ */
Polys = IritTriSrf2Polygons(PObj -> U.TriSrfs,
PolyApproxOpt ? Tolerance : Resolution,
PolyApproxUV || BoolUVBooleanState,
Normals, PolyApproxOpt);
PObjPoly = GenPolyObject("", Polys, NULL);
PObjPoly -> Attrs = AttrCopyAttributes(PObj -> Attrs);
AttrSetObjectObjAttrib(PObj, "_polygons", PObjPoly, FALSE);
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to convert a trimmed surface to a set of polygons approximating it.M
* Result is saved as an attribute on the trimmed surface. M
* If, however, approximation already exists, no computation is performed. M
* *
* PARAMETERS: M
* PObj: Trimmed surface to approximate using polygons. M
* Normals: Compute normals as well, if TRUE. M
* *
* RETURN VALUE: M
* void M
* *
* KEYWORDS: M
* ComputeTrimSrfPolygons M
*****************************************************************************/
void ComputeTrimSrfPolygons(IPObjectStruct *PObj, int Normals)
{
int Resolution = GetResolution(FALSE),
FourPerFlat = GetFourPerFlat(),
PolyApproxOpt = GetPolyApproxOptimal(),
PolyApproxUV = GetPolyApproxUV();
RealType t,
RelResolution = AttrGetObjectRealAttrib(PObj, "resolution"),
Tolerance = GetPolyApproxTol();
IPPolygonStruct *Polys;
IPObjectStruct *PObjPoly;
if (AttrGetObjectObjAttrib(PObj, "_polygons") != NULL)
return;
if (Resolution < MIN_FREE_FORM_RES)
Resolution = MIN_FREE_FORM_RES;
if (RelResolution < IP_ATTR_BAD_REAL)
Resolution = REAL_TO_INT(Resolution * RelResolution);
#ifndef __MSDOS__
/* Make the resolution more reasonable (very slow on MSDOS). */
Resolution *= 2;
#endif /* __MSDOS__ */
if (AttrGetObjectStrAttrib(PObj, "twoperflat") != NULL)
FourPerFlat = FALSE;
if (AttrGetObjectStrAttrib(PObj, "fourperflat") != NULL)
FourPerFlat = TRUE;
if ((t = AttrGetObjectRealAttrib(PObj, "u_resolution")) < IP_ATTR_BAD_REAL)
AttrSetRealAttrib(&PObj -> U.TrimSrfs -> Attr, "u_resolution", t);
if ((t = AttrGetObjectRealAttrib(PObj, "v_resolution")) < IP_ATTR_BAD_REAL)
AttrSetRealAttrib(&PObj -> U.TrimSrfs -> Attr, "v_resolution", t);
Polys = IritTrimSrf2Polygons(PObj -> U.TrimSrfs, FourPerFlat,
PolyApproxOpt ? Tolerance : Resolution,
PolyApproxUV, Normals, PolyApproxOpt);
PObjPoly = GenPolyObject("", Polys, NULL);
PObjPoly -> Attrs = AttrCopyAttributes(PObj -> Attrs);
AttrSetObjectObjAttrib(PObj, "_polygons", PObjPoly, FALSE);
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to convert a surface/list of surfaces into set of polygons. M
* *
* PARAMETERS: M
* Obj: A geometry to convert and approximate using polygons. M
* RNormals: Do we want normals as well (at vertices)? M
* *
* RETURN VALUE: M
* IPObjectStruct *: A polygonal object approximating Obj. M
* *
* KEYWORDS: M
* Geometry2Polygons M
*****************************************************************************/
IPObjectStruct *Geometry2Polygons(IPObjectStruct *Obj, RealType *RNormals)
{
IPObjectStruct *PObj;
int Normals = REAL_PTR_TO_INT(RNormals);
if (IP_IS_SRF_OBJ(Obj) ||
IP_IS_TRISRF_OBJ(Obj) ||
IP_IS_TRIMSRF_OBJ(Obj)) {
if (AttrGetObjectObjAttrib(Obj, "_polygons") != NULL)
AttrFreeOneAttribute(&Obj -> Attrs, "_polygons");
if (IP_IS_SRF_OBJ(Obj))
ComputeSurfacePolygons(Obj, Normals);
else if (IP_IS_TRISRF_OBJ(Obj))
ComputeTriSrfPolygons(Obj, Normals);
else if (IP_IS_TRIMSRF_OBJ(Obj))
ComputeTrimSrfPolygons(Obj, Normals);
PObj = CopyObject(NULL, AttrGetObjectObjAttrib(Obj, "_polygons"),
FALSE);
AttrSetObjectColor(PObj, GlblPrimColor); /* Set its default color. */
if (!Normals) {
IPPolygonStruct *Pl;
for (Pl = PObj -> U.Pl; Pl != NULL; Pl = Pl -> Pnext) {
IPVertexStruct
*V = Pl -> PVertex;
do {
IP_RST_NORMAL_VRTX(V);
V = V -> Pnext;
}
while (V != NULL && V != Pl -> PVertex);
}
}
return PObj;
}
else if (IP_IS_OLST_OBJ(Obj))
{
int i = 0;
IPPolygonStruct *P;
IPObjectStruct
*PObjAll = NULL;
while ((PObj = ListObjectGet(Obj, i++)) != NULL) {
PObj = Geometry2Polygons(PObj, RNormals);
if (PObjAll) {
if (PObj -> U.Pl) {
for (P = PObj -> U.Pl;
P -> Pnext != NULL;
P = P -> Pnext);
P -> Pnext = PObjAll -> U.Pl;
PObjAll -> U.Pl = PObj -> U.Pl;
PObj -> U.Pl = NULL;
}
IPFreeObject(PObj);
}
else {
PObjAll = PObj;
}
}
return PObjAll;
}
else {
WndwInputWindowPutStr("Unconvertable to polygons object ignored");
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to convert a surface/curve/list of these into set of polylines. M
* *
* PARAMETERS: M
* Obj: A geometry to convert and approximate using polygons. M
* Optimal: Do we want an optimal sampling but expensive approach? M
* *
* RETURN VALUE: M
* IPObjectStruct *: A polyline object approximating Obj. M
* *
* KEYWORDS: M
* Geometry2Polylines M
*****************************************************************************/
IPObjectStruct *Geometry2Polylines(IPObjectStruct *Obj, RealType *Optimal)
{
IPObjectStruct *PObj;
IPPolygonStruct *P;
if (IP_IS_CRV_OBJ(Obj)) {
return ComputeCurveIsoLines(Obj, REAL_PTR_TO_INT(Optimal));
}
else if (IP_IS_SRF_OBJ(Obj)) {
return ComputeSurfaceIsoLines(Obj, REAL_PTR_TO_INT(Optimal));
}
else if (IP_IS_TRIMSRF_OBJ(Obj)) {
return ComputeTrimSrfIsoLines(Obj, REAL_PTR_TO_INT(Optimal));
}
else if (IP_IS_TRIVAR_OBJ(Obj)) {
return ComputeTrivarIsoLines(Obj, REAL_PTR_TO_INT(Optimal));
}
else if (IP_IS_TRISRF_OBJ(Obj)) {
return ComputeTriSrfIsoLines(Obj, REAL_PTR_TO_INT(Optimal));
}
else if (IP_IS_OLST_OBJ(Obj))
{
int i = 0;
IPObjectStruct
*PObjAll = NULL;
while ((PObj = ListObjectGet(Obj, i++)) != NULL) {
PObj = Geometry2Polylines(PObj, Optimal);
if (PObjAll) {
if (PObj -> U.Pl) {
for (P = PObj -> U.Pl;
P -> Pnext != NULL;
P = P -> Pnext);
P -> Pnext = PObjAll -> U.Pl;
PObjAll -> U.Pl = PObj -> U.Pl;
PObj -> U.Pl = NULL;
}
IPFreeObject(PObj);
}
else {
PObjAll = PObj;
}
}
return PObjAll;
}
else {
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Routine to return extremum value of control mesh/polygon. M
* *
* PARAMETERS: M
* Obj: Object to bound itsextremum possible values. M
* Min: TRUE for minimum, FALSE for maximum. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A control points with extremum values. Rational are M
* Correctly porjected back to Euclidean space. M
* *
* KEYWORDS: M
* ExtremumControlPointVals M
*****************************************************************************/
IPObjectStruct *ExtremumControlPointVals(IPObjectStruct *Obj, CagdRType *Min)
{
CagdBType
FindMin = REAL_PTR_TO_INT(Min);
CagdRType *Extremum,
**Points = NULL;
int Len = 0;
CagdPointType
PType = CAGD_PT_E1_TYPE;
if (IP_IS_SRF_OBJ(Obj)) {
Points = Obj -> U.Srfs -> Points;
Len = Obj -> U.Srfs -> ULength * Obj -> U.Srfs -> VLength;
PType = Obj -> U.Srfs -> PType;
}
else if (IP_IS_CRV_OBJ(Obj)) {
Points = Obj -> U.Crvs -> Points;
Len = Obj -> U.Crvs -> Length;
PType = Obj -> U.Crvs -> PType;
}
else {
IritNonFatalError("Extremum allowed on curves/surfaces only");
return NULL;
}
Extremum = SymbExtremumCntPtVals(Points, Len, FindMin);
return GenCTLPTObject(PType, Extremum, NULL);
}
/*****************************************************************************
* DESCRIPTION: M
* Creates an exact rational quadratic circle parallel to the XY plane. M
* *
* PARAMETERS: M
* Position: Center of circle. M
* Radius: Radius of circle. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A rational quadratic Bspline curve object M
* representing a circle. M
* *
* KEYWORDS: M
* GenCircleCurveObject M
*****************************************************************************/
IPObjectStruct *GenCircleCurveObject(VectorType Position, RealType *Radius)
{
int i;
CagdPtStruct Pos;
CagdCrvStruct *CircCrv;
IPObjectStruct *CrvObj;
for (i = 0; i < 3; i++)
Pos.Pt[i] = Position[i];
CircCrv = BspCrvCreateCircle(&Pos, *Radius);
if (CircCrv == NULL)
return NULL;
CrvObj = GenCRVObject(CircCrv);
return CrvObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Creates an approximated cubic polynomial circle parallel to the XY plane. M
* *
* PARAMETERS: M
* Position: Center of circle. M
* Radius: Radius of circle. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A cubic polynomial Bspline curve object M
* representing a circle. M
* *
* KEYWORDS: M
* GenPCircleCurveObject M
*****************************************************************************/
IPObjectStruct *GenPCircleCurveObject(VectorType Position, RealType *Radius)
{
int i;
CagdPtStruct Pos;
CagdCrvStruct *CircCrv;
IPObjectStruct *CrvObj;
for (i = 0; i < 3; i++)
Pos.Pt[i] = Position[i];
CircCrv = BspCrvCreatePCircle(&Pos, *Radius);
if (CircCrv == NULL)
return NULL;
CrvObj = GenCRVObject(CircCrv);
return CrvObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Creates an arbitrary arc specified by Two end points and Center. Arc must M
* be less than 180 degree. M
* *
* PARAMETERS: M
* Start: Location of arc. M
* Center: Location of arc. M
* End: Location of arc. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A curve representing the requested arc. M
* *
* KEYWORDS: M
* GenArcCurveObject M
*****************************************************************************/
IPObjectStruct *GenArcCurveObject(VectorType Start,
VectorType Center,
VectorType End)
{
int i;
CagdPtStruct StartPt, CenterPt, EndPt;
CagdCrvStruct *ArcCrv;
IPObjectStruct *CrvObj;
for (i = 0; i < 3; i++) {
StartPt.Pt[i] = Start[i];
CenterPt.Pt[i] = Center[i];
EndPt.Pt[i] = End[i];
}
ArcCrv = BzrCrvCreateArc(&StartPt, &CenterPt, &EndPt);
if (ArcCrv == NULL)
return NULL;
CrvObj = GenCRVObject(ArcCrv);
return CrvObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Constructs a ruled surface out of the two provided curves. M
* *
* PARAMETERS: M
* Obj1, Obj2: Two polys/curves to rule a surface between. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A ruled surface object. M
* *
* KEYWORDS: M
* GenRuledSrfObject M
*****************************************************************************/
IPObjectStruct *GenRuledSrfObject(IPObjectStruct *Obj1, IPObjectStruct *Obj2)
{
IPObjectStruct
*SrfObj = NULL;
if (IP_IS_POLY_OBJ(Obj1) && IP_IS_POLY_OBJ(Obj2)) {
SrfObj = PrimGenRULEDObject(Obj1, Obj2);
}
else if (IP_IS_CRV_OBJ(Obj1) && IP_IS_CRV_OBJ(Obj2)) {
CagdSrfStruct
*RuledSrf = CagdRuledSrf(Obj1 -> U.Crvs, Obj2 -> U.Crvs, 2, 2);
if (RuledSrf == NULL)
return NULL;
SrfObj = GenSRFObject(RuledSrf);
}
else {
IritFatalError("RuledSrf: improper input geometry to ruled surface!");
}
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Construct a boolean sum surface out of a single boundary curve. M
* *
* PARAMETERS: M
* BndryCrv: A curve to fill its interior with a surface. Better be close. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A filling surface object. M
* *
* KEYWORDS: M
* GenBoolOneSrfObject M
*****************************************************************************/
IPObjectStruct *GenBoolOneSrfObject(IPObjectStruct *BndryCrv)
{
IPObjectStruct *SrfObj;
CagdSrfStruct
*BoolSumSrf = CagdOneBoolSumSrf(BndryCrv -> U.Crvs);
if (BoolSumSrf == NULL)
return NULL;
SrfObj = GenSRFObject(BoolSumSrf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Construct a boolean sum surface out of the four provided curves. M
* *
* PARAMETERS: M
* Crv1, Crv2, Crv3, Crv4: Four curves to construct a Boolean sum between. M
* *
* RETURN VALUE: M
* IPObjectStruct *: The Boolean sum surface. M
* *
* KEYWORDS: M
* GenBoolSumSrfObject M
*****************************************************************************/
IPObjectStruct *GenBoolSumSrfObject(IPObjectStruct *Crv1,
IPObjectStruct *Crv2,
IPObjectStruct *Crv3,
IPObjectStruct *Crv4)
{
IPObjectStruct *SrfObj;
CagdSrfStruct
*BoolSumSrf = CagdBoolSumSrf(Crv1 -> U.Crvs,
Crv2 -> U.Crvs,
Crv3 -> U.Crvs,
Crv4 -> U.Crvs);
if (BoolSumSrf == NULL)
return NULL;
SrfObj = GenSRFObject(BoolSumSrf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Construct a surface out of the provided curve list. M
* *
* PARAMETERS: M
* CrvList: A list of curves to approximate a surface through. M
* OtherOrder: Other order of surface. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A surface approximately traversing through the given M
* curves. M
* *
* KEYWORDS: M
* GenSrfFromCrvsObject M
*****************************************************************************/
IPObjectStruct *GenSrfFromCrvsObject(IPObjectStruct *CrvList,
RealType *OtherOrder)
{
int i,
NumCrvs = 0;
IPObjectStruct *SrfObj, *CrvObj;
CagdSrfStruct *Srf;
CagdCrvStruct *Crv,
*Crvs = NULL;
if (!IP_IS_OLST_OBJ(CrvList))
IritFatalError("SURFACE: Not object list object!");
while ((CrvObj = ListObjectGet(CrvList, NumCrvs)) != NULL) {
if (!IP_IS_CRV_OBJ(CrvObj)) {
IritNonFatalError("SURFACE: List contains non curve object(s).");
return NULL;
}
if (CrvObj -> U.Crvs -> Pnext != NULL) {
IritNonFatalError("SURFACE: nested curve lists are disallowed.");
return NULL;
}
NumCrvs++;
}
/* Chain all curves into a single list and invoke the srf constructor: */
for (i = 0; i < NumCrvs; i++) {
CrvObj = ListObjectGet(CrvList, i);
Crv = CagdCrvCopy(CrvObj -> U.Crvs);
LIST_PUSH(Crv, Crvs);
}
Crvs = CagdListReverse(Crvs);
Srf = CagdSrfFromCrvs(Crvs, REAL_PTR_TO_INT(OtherOrder));
CagdCrvFreeList(Crvs);
if (Srf == NULL)
return NULL;
SrfObj = GenSRFObject(Srf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Constructs a Sweep surface out of the CrossSection curve, Axis curve and M
* optional Scaling curve and Scaler which scales the CrossSection. M
* *
* PARAMETERS: M
* CrossSection: Cross section of sweep. M
* Axis: Axis curve of sweep. M
* Frame: Orientation specification. Either an orientation curve M
* Or a vector specification. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A sweep surface. M
* *
* KEYWORDS: M
* GenSweepSrfObject M
*****************************************************************************/
IPObjectStruct *GenSweepSrfObject(IPObjectStruct *CrossSection,
IPObjectStruct *Axis,
IPObjectStruct *Frame)
{
IPObjectStruct *SrfObj;
int FrameIsCrv = IP_IS_CRV_OBJ(Frame),
HasFrame = FrameIsCrv || IP_IS_VEC_OBJ(Frame);
CagdSrfStruct *SweepSrf;
SweepSrf = CagdSweepSrf(CrossSection -> U.Crvs, Axis -> U.Crvs, NULL, 1.0,
HasFrame ? (FrameIsCrv
? (VoidPtr) Frame -> U.Crvs
: (VoidPtr) Frame -> U.Vec)
: NULL,
FrameIsCrv);
if (SweepSrf == NULL)
return NULL;
SrfObj = GenSRFObject(SweepSrf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Constructs a Sweep surface out of the CrossSection curve, Axis curve and M
* optional Scaling curve and Scaler which scales the CrossSection. M
* *
* PARAMETERS: M
* CrossSection: Cross section of sweep. M
* Axis: Axis curve of sweep. M
* Scale: Either a numeric constant scale or a scaling scalar curve.M
* Frame: Orientation specification. Either an orientation curve M
* Or a vector specification. M
* RRefine: Refinement control. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A sweep surface. M
* *
* KEYWORDS: M
* GenSweepScaleSrfObject M
*****************************************************************************/
IPObjectStruct *GenSweepScaleSrfObject(IPObjectStruct *CrossSection,
IPObjectStruct *Axis,
IPObjectStruct *Scale,
IPObjectStruct *Frame,
RealType *RRefine)
{
IPObjectStruct *SrfObj;
int FrameIsCrv = IP_IS_CRV_OBJ(Frame),
HasFrame = FrameIsCrv || IP_IS_VEC_OBJ(Frame),
Refine = REAL_PTR_TO_INT(RRefine);
CagdCrvStruct
*AxisCrv = Axis -> U.Crvs;
CagdSrfStruct *SweepSrf;
if (IP_IS_CRV_OBJ(Scale)) {
CagdCrvStruct
*TCrv = CagdSweepAxisRefine(AxisCrv, Scale -> U.Crvs, Refine);
AxisCrv = TCrv;
}
SweepSrf = CagdSweepSrf(CrossSection -> U.Crvs, AxisCrv,
IP_IS_CRV_OBJ(Scale) ? Scale -> U.Crvs : NULL,
IP_IS_NUM_OBJ(Scale) ? Scale -> U.R : 1.0,
HasFrame ? (FrameIsCrv
? (VoidPtr) Frame -> U.Crvs
: (VoidPtr) Frame -> U.Vec)
: NULL,
FrameIsCrv);
if (AxisCrv != Axis -> U.Crvs)
CagdCrvFree(AxisCrv);
if (SweepSrf == NULL)
return NULL;
SrfObj = GenSRFObject(SweepSrf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes an approximation to the offset of a (planar) curve or a surface. M
* *
* PARAMETERS: M
* Obj: Curve to approximate its offset by Offset amount. M
* Offset: Amount of offset. M
* Tolerance: Accuracy of offset. M
* BezInterp: Do we want Bezier interpolation or approximation? M
* *
* RETURN VALUE: M
* IPObjectStruct *: An offset approximating to Obj. M
* *
* KEYWORDS: M
* GenOffsetObject M
*****************************************************************************/
IPObjectStruct *GenOffsetObject(IPObjectStruct *Obj,
RealType *Offset,
RealType *Tolerance,
RealType *BezInterp)
{
if (IP_IS_POLY_OBJ(Obj)) {
IPPolygonStruct
*Pl = GMPolyOffset(Obj -> U.Pl, IP_IS_POLYGON_OBJ(Obj),
*Offset, NULL);
IPObjectStruct
*PlObj = GenPOLYObject(Pl);
if (IP_IS_POLYGON_OBJ(Obj))
IP_SET_POLYGON_OBJ(PlObj);
else
IP_SET_POLYLINE_OBJ(PlObj);
return PlObj;
}
else if (IP_IS_SRF_OBJ(Obj)) {
IPObjectStruct *SrfObj;
CagdSrfStruct
*OffsetSrf = SymbSrfSubdivOffset(Obj -> U.Srfs, *Offset,
*Tolerance);
if (OffsetSrf == NULL)
return NULL;
SrfObj = GenSRFObject(OffsetSrf);
return SrfObj;
}
else if (IP_IS_TRIMSRF_OBJ(Obj)) {
IPObjectStruct *TSrfObj;
CagdSrfStruct
*OffsetSrf = SymbSrfSubdivOffset(Obj -> U.TrimSrfs -> Srf,
*Offset, *Tolerance);
if (OffsetSrf == NULL)
return NULL;
TSrfObj = GenTRIMSRFObject(TrimSrfNew(OffsetSrf,
TrimCrvCopyList(Obj -> U.TrimSrfs -> TrimCrvList),
TRUE));
return TSrfObj;
}
else if (IP_IS_CRV_OBJ(Obj)) {
IPObjectStruct *CrvObj;
CagdCrvStruct
*OffsetCrv = SymbCrvSubdivOffset(Obj -> U.Crvs, *Offset,
*Tolerance,
REAL_PTR_TO_INT(BezInterp));
if (OffsetCrv == NULL)
return NULL;
CrvObj = GenCRVObject(OffsetCrv);
return CrvObj;
}
else {
IritNonFatalError("Offset allowed on polys/curves/surfaces only");
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Computes an approximation to the offset of a (planar) curve or a surface. M
* This offset is computed and approximated to with a given tolerance M
* Epsilon that is related to the square of the distance between the original M
* curve and its offset approximation. M
* If Trim then regions in the curve with curvature that is larger than M
* offset distance required will be trimmed out. M
* *
* PARAMETERS: M
* Obj: Curve to approximate its offset by Offset amount. M
* Offset: Amount of offset. M
* Epsilon: Accuracy of offset. M
* Trim: Should we deal with and trim self intersecting loops? M
* BezInterp: Do we want Bezier interpolation or approximation? M
* *
* RETURN VALUE: M
* IPObjectStruct *: An offset approximating to Obj. M
* *
* KEYWORDS: M
* GenAOffsetObject M
*****************************************************************************/
IPObjectStruct *GenAOffsetObject(IPObjectStruct *Obj,
RealType *Offset,
RealType *Epsilon,
RealType *Trim,
RealType *BezInterp)
{
if (IP_IS_SRF_OBJ(Obj)) {
IritNonFatalError("Adaptive offset is not supported for surfaces");
return NULL;
}
else if (IP_IS_CRV_OBJ(Obj)) {
IPObjectStruct *CrvObj;
CagdCrvStruct
*OffsetCrv = APX_EQ(*Trim, 0.0) ?
SymbCrvAdapOffset(Obj -> U.Crvs, *Offset, *Epsilon,
NULL, REAL_PTR_TO_INT(BezInterp)) :
SymbCrvAdapOffsetTrim(Obj -> U.Crvs, *Offset,
*Epsilon, NULL,
REAL_PTR_TO_INT(BezInterp));
if (OffsetCrv == NULL)
return NULL;
else
CrvObj = GenCRVObject(OffsetCrv);
return CrvObj;
}
else {
IritNonFatalError("Offset allowed on curves/surfaces only");
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Computes an approximation to the offset of a (planar) curve or a surface. M
* This offset is computed and approximated using a least sqaure fit. M
* *
* PARAMETERS: M
* Obj: Curve to approximate its offset by Offset amount. M
* Offset: Amount of offset. M
* NumOfSamples: To sample the offset curve. M
* NumOfDOF: Number of control points in resulting approximation. M
* Order: Of resulting approximation. M
* *
* RETURN VALUE: M
* IPObjectStruct *: An offset approximating to Obj. M
* *
* KEYWORDS: M
* GenLeastSqrOffsetObject M
*****************************************************************************/
IPObjectStruct *GenLeastSqrOffsetObject(IPObjectStruct *Obj,
RealType *Offset,
RealType *NumOfSamples,
RealType *NumOfDOF,
RealType *Order)
{
CagdRType Tolerance;
if (IP_IS_CRV_OBJ(Obj)) {
CagdCrvStruct
*OffsetCrv = SymbCrvLeastSquarOffset(Obj -> U.Crvs,
*Offset,
REAL_PTR_TO_INT(NumOfSamples),
REAL_PTR_TO_INT(NumOfDOF),
REAL_PTR_TO_INT(Order),
&Tolerance);
if (OffsetCrv == NULL)
return NULL;
else
return GenCRVObject(OffsetCrv);
}
else {
IritNonFatalError("LOffset allowed on curves only");
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Computes an approximation to the offset of a (planar) curve or a surface. M
* This offset is computed and approximated using a tangent field matcing. M
* *
* PARAMETERS: M
* Obj: Curve to approximate its offset by Offset amount. M
* Offset: Amount of offset. M
* Tolerance: Accuracy of offset, measured in offset direction (normal M
* of curve) angular error, in radians. M
* *
* RETURN VALUE: M
* IPObjectStruct *: An offset approximating to Obj. M
* *
* KEYWORDS: M
* GenMatchingOffsetObject M
*****************************************************************************/
IPObjectStruct *GenMatchingOffsetObject(IPObjectStruct *Obj,
RealType *Offset,
RealType *Tolerance)
{
if (IP_IS_CRV_OBJ(Obj)) {
CagdCrvStruct
*OffsetCrv = SymbCrvMatchingOffset(Obj -> U.Crvs,
*Offset,
*Tolerance);
if (OffsetCrv == NULL)
return NULL;
else
return GenCRVObject(OffsetCrv);
}
else {
IritNonFatalError("MOffset allowed on curves only");
return NULL;
}
}
/*****************************************************************************
* DESCRIPTION: M
* Affine reparametrization, effectively changing the domain of the curve. M
* *
* PARAMETERS: M
* Obj: A curve to change its parametric domain. M
* TMin, TMax: New domain for Obj. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A curve identical to Obj but with parametric domain M
* from TMin to TMax. M
* *
* KEYWORDS: M
* CrvReparametrization M
*****************************************************************************/
IPObjectStruct *CrvReparametrization(IPObjectStruct *Obj,
RealType *TMin,
RealType *TMax)
{
IPObjectStruct *CrvObj;
CagdCrvStruct
*Crv = CAGD_IS_BEZIER_CRV(Obj -> U.Crvs) ?
CnvrtBezier2BsplineCrv(Obj -> U.Crvs) :
CagdCrvCopy(Obj -> U.Crvs);
int Len = CAGD_CRV_PT_LST_LEN(Crv) + Crv -> Order;
CagdRType MinDomain, MaxDomain,
*KV = Crv -> KnotVector;
CagdCrvDomain(Crv, &MinDomain, &MaxDomain);
/* Translate to 0.0, scale, and translate to new location. */
BspKnotAffineTrans(KV, Len, -MinDomain, 1.0);
BspKnotScale(KV, Len, (*TMax - *TMin) / (MaxDomain - MinDomain));
BspKnotAffineTrans(KV, Len, *TMin, 1.0);
CrvObj = GenCRVObject(Crv);
return CrvObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Affine reparametrization, effectively changing the domain of the surface. M
* *
* PARAMETERS: M
* Obj: A surface to change its parametric domain. M
* RDir: Direction of reparametrization. Either U or V. M
* TMin, TMax: New domain for Obj. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A surface identical to Obj but with parametric M
* domain from TMin to TMax in direction RDir. M
* *
* KEYWORDS: M
* SrfReparametrization M
*****************************************************************************/
IPObjectStruct *SrfReparametrization(IPObjectStruct *Obj,
RealType *RDir,
RealType *TMin,
RealType *TMax)
{
IPObjectStruct *SrfObj;
CagdSrfDirType
Dir = (CagdSrfDirType) REAL_PTR_TO_INT(RDir);
CagdSrfStruct
*Srf = CAGD_IS_BEZIER_SRF(Obj -> U.Srfs) ?
CnvrtBezier2BsplineSrf(Obj -> U.Srfs) :
CagdSrfCopy(Obj -> U.Srfs);
int Len = Dir == CAGD_CONST_U_DIR
? CAGD_SRF_UPT_LST_LEN(Srf) + Srf -> UOrder
: CAGD_SRF_VPT_LST_LEN(Srf) + Srf -> VOrder;
CagdRType MinDomain, MaxDomain,
MinUDomain, MaxUDomain, MinVDomain, MaxVDomain,
*KV = Dir == CAGD_CONST_U_DIR ? Srf -> UKnotVector : Srf -> VKnotVector;
CagdSrfDomain(Srf, &MinUDomain, &MaxUDomain, &MinVDomain, &MaxVDomain);
if (Dir == CAGD_CONST_U_DIR) {
MinDomain = MinUDomain;
MaxDomain = MaxUDomain;
}
else {
MinDomain = MinVDomain;
MaxDomain = MaxVDomain;
}
/* Translate to 0.0, scale, and translate to new location. */
BspKnotAffineTrans(KV, Len, -MinDomain, 1.0);
BspKnotScale(KV, Len, (*TMax - *TMin) / (MaxDomain - MinDomain));
BspKnotAffineTrans(KV, Len, *TMin, 1.0);
SrfObj = GenSRFObject(Srf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Affine reparametrization, effectively changing the domain of the trivar. M
* *
* PARAMETERS: M
* Obj: A trivariate to change its parametric domain. M
* RDir: Direction of reparametrization. Either U, V or W. M
* TMin, TMax: New domain for Obj. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A trivar identical to Obj but with parametric M
* domain from TMin to TMax in direction RDir. M
* *
* KEYWORDS: M
* TrivReparametrization M
*****************************************************************************/
IPObjectStruct *TrivReparametrization(IPObjectStruct *Obj,
RealType *RDir,
RealType *TMin,
RealType *TMax)
{
IPObjectStruct *TVObj;
TrivTVDirType
Dir = (TrivTVDirType) REAL_PTR_TO_INT(RDir);
TrivTVStruct
*TV = TRIV_IS_BEZIER_TV(Obj -> U.Trivars) ?
TrivCnvrtBezier2BsplineTV(Obj -> U.Trivars) :
TrivTVCopy(Obj -> U.Trivars);
int Len;
CagdRType *KV, MinDomain, MaxDomain, MinUDomain, MaxUDomain,
MinVDomain, MaxVDomain, MinWDomain, MaxWDomain;
TrivTVDomain(TV, &MinUDomain, &MaxUDomain,
&MinVDomain, &MaxVDomain,
&MinWDomain, &MaxWDomain);
switch (Dir) {
case TRIV_CONST_U_DIR:
Len = TRIV_TV_UPT_LST_LEN(TV) + TV -> UOrder;
KV = TV -> UKnotVector;
MinDomain = MinUDomain;
MaxDomain = MaxUDomain;
break;
case TRIV_CONST_V_DIR:
Len = TRIV_TV_VPT_LST_LEN(TV) + TV -> VOrder;
KV = TV -> VKnotVector;
MinDomain = MinVDomain;
MaxDomain = MaxVDomain;
break;
case TRIV_CONST_W_DIR:
Len = TRIV_TV_WPT_LST_LEN(TV) + TV -> WOrder;
KV = TV -> WKnotVector;
MinDomain = MinWDomain;
MaxDomain = MaxWDomain;
break;
default:
IritNonFatalError("TREPARAM: Wrong parametric direction.");
return NULL;
}
/* Translate to 0.0, scale, and translate to new location. */
BspKnotAffineTrans(KV, Len, -MinDomain, 1.0);
BspKnotScale(KV, Len, (*TMax - *TMin) / (MaxDomain - MinDomain));
BspKnotAffineTrans(KV, Len, *TMin, 1.0);
TVObj = GenTRIVARObject(TV);
return TVObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes curvature properties of the given curve. M
* *
* PARAMETERS: M
* PObj: Curve to evaluate its curvature properties. M
* Eps: Accuracy of computation. M
* *
* RETURN VALUE: M
* IPObjectStruct *: Either extremum curvature locations if Eps > 0, or M
* curvature field square curve if Eps < 0. M
* *
* KEYWORDS: M
* CrvCurvaturePts M
*****************************************************************************/
IPObjectStruct *CrvCurvaturePts(IPObjectStruct *PObj, RealType *Eps)
{
IPObjectStruct *NewPObj;
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Crvs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Crvs -> PType) > 3) {
IritNonFatalError(
"CCRVTR: Only 2 or 3 dimensional curves are supported.");
return NULL;
}
if (*Eps <= 0.0) {
CagdRType TMin, TMax;
CagdCrvStruct *CrvtrCrv2D,
*CrvtrCrv = SymbCrv3DCurvatureSqr(PObj -> U.Crvs);
CagdCrvDomain(PObj -> U.Crvs, &TMin, &TMax);
CrvtrCrv2D = SymbPrmtSclrCrvTo2D(CrvtrCrv, TMin, TMax);
CagdCrvFree(CrvtrCrv);
NewPObj = GenCRVObject(CrvtrCrv2D);
}
else {
int i;
CagdPtStruct *IPtsTmp,
*IPts = SymbCrv2DExtremCrvtrPts(PObj -> U.Crvs, *Eps);
NewPObj = IPAllocObject("", IP_OBJ_LIST_OBJ, NULL);
for (IPtsTmp = IPts, i = 0;
IPtsTmp != NULL;
IPtsTmp = IPtsTmp -> Pnext, i++) {
ListObjectInsert(NewPObj, i, GenNUMValObject(IPtsTmp -> Pt[0]));
}
CagdPtFreeList(IPts);
ListObjectInsert(NewPObj, i, NULL);
}
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes curvature properties of the given surface. M
* *
* PARAMETERS: M
* PObj: Surface to compute curvature properties for. M
* RPtType: Point type of output. M
* RDir: Either curvature in U or V or total upper bound. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A curvature bound field for surface PObj. M
* *
* KEYWORDS: M
* SrfCurvatureBounds M
*****************************************************************************/
IPObjectStruct *SrfCurvatureBounds(IPObjectStruct *PObj,
RealType *RPtType,
RealType *RDir)
{
IPObjectStruct *NewPObj;
CagdSrfStruct *TSrf, *CrvtrSrfBound;
CagdPointType
PtType = (CagdPointType) REAL_PTR_TO_INT(RPtType);
CagdSrfDirType
Dir = (CagdSrfDirType) REAL_PTR_TO_INT(RDir);
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) > 3) {
IritNonFatalError(
"SCRVTR: Only 2 or 3 dimensional curves are supported.");
return NULL;
}
switch (Dir) {
case CAGD_CONST_U_DIR:
case CAGD_CONST_V_DIR:
CrvtrSrfBound = SymbSrfIsoDirNormalCurvatureBound(PObj -> U.Srfs,
Dir);
break;
default:
CrvtrSrfBound = SymbSrfCurvatureUpperBound(PObj -> U.Srfs);
break;
}
switch (PtType) {
case CAGD_PT_P1_TYPE:
break;
case CAGD_PT_E1_TYPE:
case CAGD_PT_E3_TYPE:
case CAGD_PT_P3_TYPE:
TSrf = CagdCoerceSrfTo(CrvtrSrfBound, PtType);
CagdSrfFree(CrvtrSrfBound);
CrvtrSrfBound = TSrf;
break;
default:
CagdSrfFree(CrvtrSrfBound);
IritNonFatalError("SCRVTR: Wrong point type coercion.");
return NULL;
}
NewPObj = GenSRFObject(CrvtrSrfBound);
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes the Gauss curvature surface of the given surface. M
* *
* PARAMETERS: M
* PObj: Surface to compute its gauss curvature surface for. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A Gauss curvature surface of PObj. M
* *
* KEYWORDS: M
* SrfGaussCurvature M
*****************************************************************************/
IPObjectStruct *SrfGaussCurvature(IPObjectStruct *PObj)
{
IPObjectStruct *NewPObj;
CagdSrfStruct *GaussSrf;
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) > 3) {
IritNonFatalError(
"SGauss: Only 2 or 3 dimensional surfaces are supported.");
return NULL;
}
GaussSrf = SymbSrfGaussCurvature(PObj -> U.Srfs);
NewPObj = GenSRFObject(GaussSrf);
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes the Mean curvature square surface of the given surface. M
* *
* PARAMETERS: M
* PObj: Surface to compute its mean curvature square surface for. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A Mean curvature square surface of PObj. M
* *
* KEYWORDS: M
* SrfMeanSqrCurvature M
*****************************************************************************/
IPObjectStruct *SrfMeanSqrCurvature(IPObjectStruct *PObj)
{
IPObjectStruct *NewPObj;
CagdSrfStruct *MeanSrf;
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) > 3) {
IritNonFatalError(
"SMeanSqr: Only 2 or 3 dimensional surfaces are supported.");
return NULL;
}
MeanSrf = SymbSrfMeanCurvatureSqr(PObj -> U.Srfs);
NewPObj = GenSRFObject(MeanSrf);
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes the isoparametric focal surface of the given surface. M
* *
* PARAMETERS: M
* PObj: Surface to compute its focal surface using isoparametric M
* normal curvature direction. M
* RDir: Either iso focal surface in U or V. M
* *
* RETURN VALUE: M
* IPObjectStruct *: An iso focal surface of surface PObj. M
* *
* KEYWORDS: M
* SrfIsoFocalSrf M
*****************************************************************************/
IPObjectStruct *SrfIsoFocalSrf(IPObjectStruct *PObj, RealType *RDir)
{
IPObjectStruct *NewPObj;
CagdSrfStruct *IsoFocalSrf;
CagdSrfDirType
Dir = (CagdSrfDirType) REAL_PTR_TO_INT(RDir);
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) > 3) {
IritNonFatalError(
"IsoFocal: Only 2 or 3 dimensional surfaces are supported.");
return NULL;
}
IsoFocalSrf = SymbSrfIsoFocalSrf(PObj -> U.Srfs, Dir);
NewPObj = GenSRFObject(IsoFocalSrf);
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Computes the (mean) evolute curve/surface of the given curve/surface. M
* *
* PARAMETERS: M
* PObj: Curve/Surface to compute its (mean) evolute for. M
* *
* RETURN VALUE: M
* IPObjectStruct *: A (mean) evolute curve/surface of PObj. M
* *
* KEYWORDS: M
* FreeformEvolute M
*****************************************************************************/
IPObjectStruct *FreeformEvolute(IPObjectStruct *PObj)
{
IPObjectStruct *NewPObj;
if (IP_IS_CRV_OBJ(PObj)) {
CagdCrvStruct *EvoluteCrv, *EvoluteCrvAux;
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Crvs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Crvs -> PType) > 3) {
IritNonFatalError(
"EVOLUTE: Only 2 or 3 dimensional curves are supported.");
return NULL;
}
EvoluteCrvAux = SymbCrv3DRadiusNormal(PObj -> U.Crvs);
EvoluteCrv = SymbCrvAdd(PObj -> U.Crvs, EvoluteCrvAux);
CagdCrvFree(EvoluteCrvAux);
NewPObj = GenCRVObject(EvoluteCrv);
}
else if (IP_IS_SRF_OBJ(PObj)) {
CagdSrfStruct *EvoluteSrf, *EvoluteSrfAux;
if (CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) < 2 ||
CAGD_NUM_OF_PT_COORD(PObj -> U.Srfs -> PType) > 3) {
IritNonFatalError(
"EVOLUTE: Only 2 or 3 dimensional surfaces are supported.");
return NULL;
}
EvoluteSrfAux = SymbSrfMeanEvolute(PObj -> U.Srfs);
EvoluteSrf = SymbSrfAdd(PObj -> U.Srfs, EvoluteSrfAux);
CagdSrfFree(EvoluteSrfAux);
NewPObj = GenSRFObject(EvoluteSrf);
}
return NewPObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Merges two surfaces into one in specified Dir and SameEdge flag. M
* *
* PARAMETERS: M
* Srf1, Srf2: Two surfaces to merge. M
* Dir: Direction of merge. Either U or V. M
* SameEdge: Do Srf1 and Srf2 share a common edge? M
* *
* RETURN VALUE: M
* IPObjectStruct *: A surface result of the merge. M
* *
* KEYWORDS: M
* MergeSrfSrf M
*****************************************************************************/
IPObjectStruct *MergeSrfSrf(IPObjectStruct *Srf1,
IPObjectStruct *Srf2,
RealType *Dir,
RealType *SameEdge)
{
IPObjectStruct *SrfObj;
CagdSrfStruct
*Srf = CagdMergeSrfSrf(Srf1 -> U.Srfs, Srf2 -> U.Srfs,
(CagdSrfDirType) REAL_PTR_TO_INT(Dir),
REAL_PTR_TO_INT(SameEdge), TRUE);
SrfObj = GenSRFObject(Srf);
return SrfObj;
}
/*****************************************************************************
* DESCRIPTION: M
* Merge two curves/ctl points into one curve by adding a linear segment M
* between the first end point to second start point. M
* *
* PARAMETERS: M
* PObj1, PObj2: Either curve or a control point to merge. M
* *
* RETURN VALUE: M
* IPObjectStruct *: Merged curve. M
* *
* KEYWORDS: M
* MergeCurvesAndCtlPoints M
*****************************************************************************/
IPObjectStruct *MergeCurvesAndCtlPoints(IPObjectStruct *PObj1,
IPObjectStruct *PObj2)
{
IPObjectStruct *CrvObj;
CagdCrvStruct
*Crv = NULL;
CagdPtStruct Pt1, Pt2;
if (IP_IS_CRV_OBJ(PObj1)) {
if (IP_IS_CRV_OBJ(PObj2)) {
Crv = CagdMergeCrvCrv(PObj1 -> U.Crvs, PObj2 -> U.Crvs, TRUE);
}
else if (IP_IS_CTLPT_OBJ(PObj2)) {
CagdRType
*Coords2 = PObj2 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
Crv = CagdMergeCrvPt(PObj1 -> U.Crvs, &Pt2);
}
else
IritFatalError("Curve/CtlPt was expected.");
}
else if (IP_IS_CTLPT_OBJ(PObj1)) {
CagdRType
*Coords1 = PObj1 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt1.Pt, &Coords1, -1, PObj1 -> U.CtlPt.PtType);
if (IP_IS_CRV_OBJ(PObj2)) {
Crv = CagdMergePtCrv(&Pt1, PObj2 -> U.Crvs);
}
else if (IP_IS_CTLPT_OBJ(PObj2)) {
CagdRType
*Coords2 = PObj2 -> U.CtlPt.Coords;
CagdCoerceToE3(Pt2.Pt, &Coords2, -1, PObj2 -> U.CtlPt.PtType);
Crv = CagdMergePtPt(&Pt1, &Pt2);
}
else
IritFatalError("Curve/CtlPt was expected.");
}
else
IritFatalError("Curve/CtlPt was expected.");
if (Crv == NULL)
return NULL;
CrvObj = GenCRVObject(Crv);
return CrvObj;
}